#!/usr/bin/perl 
#
# (C) Copyright 2010- Hewlett-Packard Development Company, L.P.
# 
#  $Id: createsquser.pl 17709 2012-04-25 18:16:13Z chantal.tremblay@hp.com $
#

use strict;
use 5.008000;
use warnings;
use POSIX;
use Getopt::Long; 
use File::Basename;

use lib '/opt/hp/nv/lib/perl';
use config ':all';
use instance ':all';

# possible error returns
use constant {
    OK => 0,
    WARN => 1,
    CRITICAL => 2,
    UNKNOWN => 3,
};

# Global variables

# common global variables
my $proceed=1;
my $done=0;

my $myscriptname = "createsquser";
my $status_file="$nvpath/instance/status/" . $myscriptname;
my $revision = '$Revision: 17709 $';
$revision =~ s/\$//g;

# script specific globals
my $user_cmd = "$nvpath/instance/sq_user";

# command line options
my %gv_opts = ( group => "seaquest",
		password  => "redhat06",
		qpid_port => "50008"
              );
;

# DO NOT DELETE/DO NOT MODIFY
#
# This sub calls module routine to log informational message to log file
# after first prepending program name; timestamp will be added in
# Perl module
#
sub log_msg
{
    my $message = shift;
    my $infomessage;

    $infomessage = basename($0) . ": INFO: ". $message . "\n";
    instance_log_event($infomessage);

}

# DO NOT DELETE/DO NOT MODIFY
#
# This sub calls module routine to log warning message to log file
# after first prepending program name and Warning label; a timestamp 
# will be added in Perl module
#
sub log_warn
{
    my $message = shift;
    my $warnmessage;

    $warnmessage = basename($0) . ": WARNING: ". $message . "\n";
    instance_log_event($warnmessage);

}

# DO NOT DELETE/DO NOT MODIFY
#
# This sub calls module routine to log error message to log file
# after first prepending program name; timestamp will be added in
# Perl module; the program will then exit
#
sub logerr_n_die
{
    my $message = shift;
    my $errormessage;

    $errormessage = basename($0) . ": ERROR: ". $message . "\n";
    print STDERR $errormessage;
    
    instance_log_event($errormessage);
    exit(CRITICAL);

}


#
# This sub checks for any requirements that must be met before 
# the configuration is performed.
#
sub pre_req_check
{
    return(OK);
}

#
# This sub verifies that the work done is complete and in such a state 
# that it is ready for the next step to be done
#
sub post_check
{
	if (!$gv_opts{dryrun} && !is_valid_user($gv_opts{squser})) {
	    logerr_n_die("Add User:$gv_opts{squser} failed!");
	}
	
	return(OK);
}

# CHANGE FOR YOUR NEEDS
#
# This sub checks the script status to determine whether 
# the script has already been run successfully.
# The status file could just hold "completed", for example,
# or it could hold a count of how many things were processed last time,
# e.g. number of nodes, or number of disks, etc.  So that a comparison
# can be made to see if processing must be done again.
#
sub get_status(;$)
{
    my $prefix = shift;
    $prefix = '' unless (defined $prefix);
        
    # Keep the open and close of the file along with the line processing

    # if we haven't yet written this file then we surely must proceed
    return($proceed) if (!-e $status_file);

    open(IFH,$status_file) || logerr_n_die("Can't open file $status_file: $!");
    while (<IFH>) # loop through the whole file
    {
        next if (/^\s*$/);
        next if (/^\#/);

        # ADD HERE THE PROCESSING THAT MAKES SENSE FOR YOUR CODE!
        # IN THIS EXAMPLE WE CHECK FOR 'completed'
        if (/^$prefix:completed/) {
            close(IFH);
            return($done);
        }
    }

    close(IFH);
    return($proceed);
}

#
# This sub sets the script status to be examined
# the next time the script is run.
# The status file could just hold "completed", for example,
# or it could hold a count of how many things were processed last time,
# e.g. number of nodes, or number of disks, etc.  So that a comparison
# can be made to see if processing must be done again.
#
sub set_status($;$)
{
    my ($statusmsg, $prefix) = @_;       

    return if ($gv_opts{dryrun});  # don't set status if test mode

    # Keep the open and close of the file
    open(OFH,">>$status_file") || logerr_n_die("Can't open file $status_file: $!");

    # ADD HERE THE PROCESSING THAT MAKES SENSE FOR YOUR CODE!
    print OFH "$prefix:$statusmsg\n";

    close(OFH);

}

# This sub will create a temp xml file using the arguments
sub create_temp_xml
{
	# Create the temp xml file
    my $tmp_xml = "/tmp/tmpuser_$$.xml";
    
    # actually, these values are unnecessary, just to fill the place
    my ($group, $password, $qpid_port) 
	    = ($gv_opts{group}, $gv_opts{password}, $gv_opts{qpid_port}); 
    
    open(OFH,">$tmp_xml") || logerr_n_die("Can't create file $tmp_xml !");

    # Now generate the temp xml file
    print OFH "<initial_user>\n"
            . "    <groups>\n"
            . "        <group>$group</group>\n"
            . "    </groups>\n"
            . "    <users>\n"
            . "        <user password=\"$password\""
            . "              group_name=\"$group\""
            . "              qpid_port=\"$qpid_port\">$gv_opts{squser}</user>\n"
            . "    </users>\n"
            . "    </initial_user>\n";

    close(OFH);

    return $tmp_xml;
}

# this sub run the command if not for test mode, or print it to stdout
sub run_cmd($)
{
    my $cmd = shift;

    if ($gv_opts{dryrun}) {
        print STDOUT $cmd . "\n";
        $? = 0;
    }
    else {
        system $cmd;
    }
}

# perform the work
sub perform_config
{
    my $force_flag = get_force_flag();
    my $status_value = get_status($gv_opts{squser});

    return(OK) if (!$force_flag && ($status_value == $done));

    # First, create the temp xml file
    my $tmp_xml = create_temp_xml();

    if (is_valid_user($gv_opts{squser})) {
        # remove it if exists
        log_msg("User $gv_opts{squser} already exists, remove it first");
        my $cmd = "$user_cmd -o del -f $tmp_xml -w >/dev/null 2>&1";
        run_cmd($cmd);

        if (WIFEXITED($?) && (WEXITSTATUS($?) != 0)) {
	    unlink($tmp_xml);
            set_status("remove_failed", $gv_opts{squser});
	    logerr_n_die("An error occured when execute the cmd $cmd:". WEXITSTATUS($?));		
        }
    }

    # Now we call sq_user to create user
    my $cmd = "$user_cmd -o add -f $tmp_xml";
	
    $cmd .= " -d" if($gv_opts{debug});
    $cmd .= " -v" if($gv_opts{verbose});
    $cmd .= " 2>&1";
	
    run_cmd($cmd);
	
    unlink($tmp_xml);
    if (WIFEXITED($?) && (WEXITSTATUS($?) != 0)) {
        logerr_n_die("An error occured when execute the cmd $cmd:". WEXITSTATUS($?));		
    }
	
    if (!$gv_opts{dryrun}) {	
        # Update .bashrc

        # For each user, configure the SHARED_HARDWARE variable
        # based on the configuration of the instance framework
        # Also, define the configuration type, if shared, either
        # "shared" or "segmented".  But, for now we only support
        # the "shared" configuration.
        my $config = get_inst_config_type();
        my $shared = ($config eq "shared") ? "YES" : "NO";

        my $env_sh = "/home/$gv_opts{squser}/myenv.sh";
        if (!open(MYENV, ">$env_sh")) {
            set_status("open_failed", $gv_opts{squser});
            logerr_n_die("Cannot create $env_sh");
        }

        print MYENV "export SHARED_HARDWARE=$shared\n";
        if ($config eq "shared") {
            print MYENV "export SHARED_TYPE=$config\n";
        }
    
        close MYENV;

        # change the owner to squser
        $cmd = "/bin/chown $gv_opts{squser}.$gv_opts{group} $env_sh";
        run_cmd($cmd);
        if (WIFEXITED($?) && (WEXITSTATUS($?) != 0)) {
            set_status("chown_failed", $gv_opts{squser});
	    logerr_n_die("An error occured when execute the cmd $cmd:". WEXITSTATUS($?    ));
        }
		
        set_status("completed", $gv_opts{squser});
    }

    return(OK);
}

#
# usage
#
sub usage
{
print <<"EOF";

This script will call the sq_user.pl script to add or delete the squser you want.
createsquser    --squser=<squser ID Name> 
                [--group=<seaquest(default)>]
                [--password|pw=<Password for user>] 
                [--qpid_port|qp=<50008(default)>] [--debug|d]
                [--verbose|v]
EOF

exit(UNKNOWN);
}



### Main ###

# DO NOT DELETE/DO NOT MODIFY
#
# Do not delete any of the following subroutine calls.  
# You can add more code to perform_config
#

# Process input arguments

&GetOptions(\%gv_opts, 
             "squser=s",
	     "group=s",
	     "password=s",
	     "qpid_port=i",
             "dryrun|test",
	     "verbose|v",
	     "debug|d",
	     "help" =>\&usage) or usage(); 
	
logerr_n_die("Invaild user provided!") unless(defined $gv_opts{squser});	

log_msg("Starting script: revision number $revision");

pre_req_check;

perform_config;

post_check;

# Return success 
exit(OK);
